package com.pig4cloud.pig.ads.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dy.sdk.client.DyTtClient;
import com.dy.sdk.model.request.tt.TtEventsTrackCreateRequest;
import com.dy.sdk.model.request.tt.TtEventsTrackListRequest;
import com.dy.sdk.model.request.tt.TtOptimizedGoalRequest;
import com.dy.sdk.model.response.tt.TtResponse;
import com.google.common.collect.Lists;
import com.pig4cloud.pig.ads.pig.mapper.AdAssetsTrackMapper;
import com.pig4cloud.pig.ads.service.AdAssetsService;
import com.pig4cloud.pig.ads.service.AdAssetsTrackService;
import com.pig4cloud.pig.ads.service.TtAccesstokenService;
import com.pig4cloud.pig.api.entity.AdAssets;
import com.pig4cloud.pig.api.entity.AdAssetsTrack;
import com.pig4cloud.pig.api.util.JsonUtil;
import com.pig4cloud.pig.api.vo.AdAssetsTrackReq;
import com.pig4cloud.pig.common.core.constant.enums.PlatformTypeEnum;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 监测链接组表
 * @author  chenxiang
 * @version  2022-04-06 13:31:02
 * table: ad_assets_track
 */
@Log4j2
@Service("adAssetsTrackService")
@RequiredArgsConstructor
public class AdAssetsTrackServiceImpl extends ServiceImpl<AdAssetsTrackMapper, AdAssetsTrack> implements AdAssetsTrackService {

	private final TtAccesstokenService ttAccesstokenService;
	private final AdAssetsService adAssetsService;

	/**
	 * 调用头条 - 创建监测组链接
	 * @param record
	 * @return
	 */
	@Override
	public R createEventTrackUrl(AdAssetsTrack record){
		try {
			// 创建监测链接组头条不返回监测链接组ID，故验证监测链接组名称不能重复
			AdAssetsTrack assetsTrack = this.getOne(Wrappers.<AdAssetsTrack>lambdaQuery()
					.eq(AdAssetsTrack::getTrackUrlGroupName,record.getTrackUrlGroupName())
					.eq(AdAssetsTrack::getAssetId,record.getAssetId())
					.eq(AdAssetsTrack::getDeleted, 0));
			if (Objects.nonNull(assetsTrack)){
				log.error(">>>>>>监测链接组名称已存在<<<<<<");
				return R.failed("监测链接组名称已存在");
			}
			String advertiserId = record.getAdvertiserId();
			String accessToken = ttAccesstokenService.fetchAccesstoken(advertiserId);
			DyTtClient ttClient = new DyTtClient("");
			TtEventsTrackCreateRequest eventsTrackCreateRequest = new TtEventsTrackCreateRequest();
			eventsTrackCreateRequest.setAdvertiser_id(Long.valueOf(advertiserId));
			eventsTrackCreateRequest.setAssets_id(record.getAssetId());
			eventsTrackCreateRequest.setDownload_url(record.getDownloadUrl());
			List<Map<String,Object>> listMap = Lists.newArrayList();
			Map<String,Object> track_url_groups = new HashMap<>();
			track_url_groups.put("action_track_url",record.getActionTrackUrl());
			track_url_groups.put("track_url_group_name",record.getTrackUrlGroupName());
			listMap.add(track_url_groups);
			eventsTrackCreateRequest.setTrack_url_groups(listMap);
			// 调用头条API《创建监测组链接》
			log.info(">>>>>>调用头条创建监测组链接params：{}", JSON.toJSONString(eventsTrackCreateRequest));
			String result = ttClient.call4Post(eventsTrackCreateRequest, accessToken);
			log.info(">>>>>>调用头条创建监测组链接result：{}",result);
			TtResponse response = JSON.parseObject(result, TtResponse.class);
			if ("0".equals(response.getCode())){
				record.setSoucreStatus(1);
				this.save(record);
				// 创建成功， 异步线程拉取一次监测链接组
				ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
				executor.schedule(new Runnable() {
					@Override
					public void run() {
						synEventTrack(record);
					}
				}, 5, TimeUnit.SECONDS);
				executor.shutdown();
				return R.ok(record);
			}else{
				log.error(">>>>>>调用头条创建监测组链接异常：{}",response.getMessage());
				return R.failed(response.getMessage());
			}
		} catch (Exception e) {
			log.error(">>>>>>调用头条创建监测组链接异常：{}",e.getMessage());
		}
		return R.failed();
	}
	/**
	 * 获取事件资产下的监测链接组
	 * @param record
	 * @return
	 */
	@Override
	public R getTrackUrl(AdAssetsTrackReq record){
		try {
			String advertiserId = record.getAdvertiserId();
			String appCloudId = record.getAppCloudId();
			// 获取到资产信息
			AdAssets adAssets = adAssetsService.getOne(Wrappers.<AdAssets>lambdaQuery().eq(AdAssets::getAdvertiserId,advertiserId)
					.eq(StringUtils.isNotBlank(appCloudId),AdAssets::getAppCloudId,appCloudId).eq(AdAssets::getDeleted,0));
			if (Objects.isNull(adAssets)){
				return R.failed("应用下没有资产,请先创建");
			}
			List<AdAssetsTrack> adAssetsTrackList = this.list(Wrappers.<AdAssetsTrack>lambdaQuery()
					.eq(AdAssetsTrack::getAdvertiserId,advertiserId)
					.eq(StringUtils.isNotBlank(appCloudId),AdAssetsTrack::getAppCloudId,appCloudId)
					.eq(AdAssetsTrack::getAssetId,adAssets.getAssetId())
					.eq(AdAssetsTrack::getDeleted,0));
			return R.ok(adAssetsTrackList);
		} catch (Exception e) {
			log.error(">>>>>>获取事件资产下的监测链接组异常：{}",e.getMessage());
		}
		return R.failed();
	}
	/**
	 * 获取优化目标
	 * @param record
	 * @return
	 */
	@Override
	public R getOptimizedGoal(AdAssetsTrackReq record){
		try {
			String advertiserId = record.getAdvertiserId();
			String appCloudId = record.getAppCloudId();
			// 获取到资产信息
			AdAssets adAssets = adAssetsService.getOne(Wrappers.<AdAssets>lambdaQuery().eq(AdAssets::getAdvertiserId,advertiserId)
					.eq(StringUtils.isNotBlank(appCloudId),AdAssets::getAppCloudId,appCloudId).eq(AdAssets::getDeleted,0));
			if (Objects.isNull(adAssets)){
				return R.failed("应用下没有资产,请先创建");
			}
			// 获取token
			String accessToken = ttAccesstokenService.fetchAccesstoken(advertiserId);
			DyTtClient ttClient = new DyTtClient("");
			TtOptimizedGoalRequest optimizedGoalRequest = new TtOptimizedGoalRequest();
			optimizedGoalRequest.setAdvertiser_id(Long.valueOf(advertiserId));
			optimizedGoalRequest.setLanding_type("APP");
			optimizedGoalRequest.setMarketing_purpose("CONVERSION");
			optimizedGoalRequest.setAsset_type("APP");
			optimizedGoalRequest.setPackage_name(adAssets.getPackageName());
			optimizedGoalRequest.setApp_type("ANDROID");
			String result = ttClient.call4Get(optimizedGoalRequest, accessToken);
			TtResponse response = JSON.parseObject(result, TtResponse.class);
			if ("0".equals(response.getCode())){
				return R.ok(response.getData());
			}else{
				log.error(">>>>>>获取优化目标异常：{}",response.getMessage());
				return R.failed(response.getMessage());
			}
		} catch (Exception e) {
			log.error(">>>>>>获取优化目标异常：{}",e.getMessage());
		}
		return R.failed();
	}
	/**
	 * 创建成功，异步线程拉取一次监测链接组
	 * @param record
	 */
	public void synEventTrack(AdAssetsTrack record){
		// 获取事件资产下的监测链接组
		List<AdAssetsTrack> adAssetsTrackList = getAssetsTrack(record);
		// 保存监测链接组
		saveAssetsTrack(adAssetsTrackList, record);
		log.info(">>>>>>监测链接组创建成功，异步线程拉取一次监测链接组成功！");
	}
	/**
	 * 获取事件资产下的监测链接组
	 * @param adAssetsTrack
	 * @return
	 */
	public List<AdAssetsTrack> getAssetsTrack(AdAssetsTrack adAssetsTrack){
		List<AdAssetsTrack> adAssetsList = Lists.newArrayList();
		try{
			// 获取token
			String accessToken = ttAccesstokenService.fetchAccesstoken(adAssetsTrack.getAdvertiserId());
			int page = 1;
			while (true){
				DyTtClient ttClient = new DyTtClient("");
				TtEventsTrackListRequest eventsTrackListRequest = new TtEventsTrackListRequest();
				eventsTrackListRequest.setAdvertiser_id(Long.valueOf(adAssetsTrack.getAdvertiserId()));
				eventsTrackListRequest.setAsset_id(adAssetsTrack.getAssetId());
				eventsTrackListRequest.setDownload_url(adAssetsTrack.getDownloadUrl());
				eventsTrackListRequest.setPage(page);
				log.info(">>>>>>获取事件资产下的监测链接组params：{}", JSON.toJSONString(eventsTrackListRequest));
				String result = ttClient.call4Get(eventsTrackListRequest, accessToken);
				log.info(">>>>>>获取事件资产下的监测链接组result：{}", result);
				TtResponse response = JSON.parseObject(result, TtResponse.class);
				if ("0".equals(response.getCode())){
					JSONObject jsonObject = response.getData();
					JSONArray jsonArray = jsonObject.getJSONArray("track_url_groups");
					for (Object object : jsonArray){
						JSONObject jsonObj = JsonUtil.toSnakeObject(JSON.toJSONString(object), JSONObject.class);
						AdAssetsTrack assetsTrack = JSON.toJavaObject(jsonObj, AdAssetsTrack.class);
						adAssetsList.add(assetsTrack);
					}

					JSONObject objectPage = jsonObject.getJSONObject("page_info");
					int totalPage = objectPage.getIntValue("total_page");
					if (page >= totalPage){
						break;
					}
					page++;
				}else{
					log.error(">>>>>>获取事件资产下的监测链接组异常：{}",response.getMessage());
					break;
				}
			}
		} catch (Exception e){
			log.error(">>>>>>获取事件资产下的监测链接组异常：{}",e.getMessage());
		}
		return adAssetsList;
	}

	/**
	 * 保存监测链接组
	 * @param adAssetsTrackList
	 * @param adAssetsTrackReq
	 */
	public void saveAssetsTrack(List<AdAssetsTrack> adAssetsTrackList, AdAssetsTrack adAssetsTrackReq) {
		List<AdAssetsTrack> insertList = Lists.newArrayList();
		List<AdAssetsTrack> updateList = Lists.newArrayList();
		// 查询DB已经存在的链接组
		List<AdAssetsTrack> adAssetsTrackListDb = this.list(Wrappers.<AdAssetsTrack>lambdaQuery()
				.eq(AdAssetsTrack::getAdvertiserId, adAssetsTrackReq.getAdvertiserId())
				.eq(AdAssetsTrack::getAssetId, adAssetsTrackReq.getAssetId())
				.eq(AdAssetsTrack::getDownloadUrl, adAssetsTrackReq.getDownloadUrl())
				.eq(AdAssetsTrack::getDeleted, 0));
		if (CollectionUtils.isNotEmpty(adAssetsTrackList)) {
			for (AdAssetsTrack adAssetsTrack : adAssetsTrackList) {
				// 创建监测链接组头条不返回监测链接组ID，故通过监测链接组名称验证是否重复
				List<AdAssetsTrack> adAssetsTracks = adAssetsTrackListDb.stream()
						.filter(v -> v.getTrackUrlGroupName().equals(adAssetsTrack.getTrackUrlGroupName())).collect(Collectors.toList());
				if (CollectionUtils.isEmpty(adAssetsTracks)) {
					adAssetsTrack.setMediaCode(Integer.valueOf(PlatformTypeEnum.TT.getValue()));
					adAssetsTrack.setAdvertiserId(adAssetsTrackReq.getAdvertiserId());
					adAssetsTrack.setAssetId(adAssetsTrackReq.getAssetId());
					adAssetsTrack.setPackageName(adAssetsTrackReq.getPackageName());
					adAssetsTrack.setAppCloudId(Long.valueOf(adAssetsTrackReq.getAppCloudId()));
					adAssetsTrack.setAppName(adAssetsTrackReq.getAppName());
					adAssetsTrack.setDownloadUrl(adAssetsTrackReq.getDownloadUrl());
					adAssetsTrack.setSoucreStatus(2);
					insertList.add(adAssetsTrack);
				} else {
					AdAssetsTrack assetsTrack = adAssetsTracks.get(0);
					assetsTrack.setTrackUrlGroupId(adAssetsTrack.getTrackUrlGroupId());
					assetsTrack.setActionTrackUrl(adAssetsTrack.getActionTrackUrl());
					assetsTrack.setTrackUrl(adAssetsTrack.getTrackUrl());
					assetsTrack.setVideoPlayTrackUrl(adAssetsTrack.getVideoPlayTrackUrl());
					assetsTrack.setVideoPlayDoneTrackUrl(adAssetsTrack.getVideoPlayDoneTrackUrl());
					assetsTrack.setVideoPlayEffectiveTrackUrl(adAssetsTrack.getVideoPlayEffectiveTrackUrl());
					updateList.add(assetsTrack);
				}
			}
		}
		if (CollectionUtils.isNotEmpty(insertList)) {
			// 批量添加
			this.saveBatch(insertList);
		}
		if (CollectionUtils.isNotEmpty(updateList)) {
			// 批量更新
			this.updateBatchById(updateList);
		}
	}
}


